package com.guomei.controller.pay;

import com.guomei.bean.PayRequest;
import com.guomei.bean.User;
import com.guomei.bean.curse.Course;
import com.guomei.bean.curse.CourseOrder;
import com.guomei.bean.curse.domain.DistributeRecord;
import com.guomei.bean.curse.domain.UserDistributorCourseRel;
import com.guomei.bean.exam.domain.Exam;
import com.guomei.bean.exam.domain.ExamEnroll;
import com.guomei.constans.RedisConstants;
import com.guomei.mapper.UserMapper;
import com.guomei.mapper.curse.*;
import com.guomei.service.curse.CourseOrderService;
import com.guomei.service.pay.PaymentStrategy;
import com.guomei.utils.RedisUtils;
import com.guomei.utils.Result;
import com.guomei.utils.ValidationUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@RestController
@RequestMapping("/api1/pay")
@Slf4j
public class PaymentController {
    @Resource
    private PaymentStrategy paymentStrategy;

    @Resource
    private CourseOrderService courseOrderService;

    @Resource
    private RedisUtils redisUtils;

    @Resource
    private CourseOrderMapper courseOrderMapper;
    @Resource
    private CourseMapper courseMapper;
    @Resource
    DistributeRecordMapper distributeRecordMapper;
    @Resource
    UserMapper userMapper;
    @Resource
    UserDistributorCourseRelMapper userDistributorCourseRelMapper;
    @Resource
    private ExamEnrollMapper examEnrollMapper;

    /**
     * 创建支付
     */
    @PostMapping("/create")
    public Result<?> createPayment(@Valid @RequestBody PayRequest request, BindingResult result) {

        // request.getOutTradeNo(); Course、 ExamEnroll
        if (request.getTotalAmount() != null && request.getTotalAmount().compareTo(BigDecimal.ZERO) == 0) {
            if (!request.getOutTradeNo().startsWith("EXAM")) {
                CourseOrder courseOrder = courseOrderMapper.selectByOrderNo(request.getOutTradeNo());
                if (courseOrder != null) {
                    CourseOrder courseOrder1 = new CourseOrder();
                    courseOrder1.setPayStatus(Short.valueOf("1"));
                    courseOrder1.setId(courseOrder.getId());
                    courseOrder1.setOrderStatus(Short.valueOf("0"));
                    courseOrder1.setPayAmount(request.getTotalAmount());
                    courseOrder1.setPayTime(LocalDateTime.now());
                    courseOrderMapper.updateById(courseOrder1);
                    if (courseOrder.getCourseId() != null) {
                        Course course = courseMapper.selectById(courseOrder.getCourseId());
                        if (course != null && course.getDistributionType() == 0) {
                            DistributeRecord distributeRecord = new DistributeRecord();
                            distributeRecord.setStudentId(courseOrder.getUserId());
                            User user = userMapper.selectById(courseOrder.getUserId());
                            if (user != null && user.getParentId() != null) {
                                distributeRecord.setDistributorId(user.getParentId());
                                distributeRecord.setCourseId(courseOrder.getCourseId());
                                distributeRecord.setOrderId(courseOrder.getId());
                                distributeRecord.setActualPayAmount(request.getTotalAmount());
                                distributeRecord.setDistributionRatio(course.getDistributionRatio());
                                distributeRecord.setDistributeAmount(BigDecimal.valueOf(0));
                                distributeRecord.setStatus(Short.valueOf("0"));
                                distributeRecordMapper.insert(distributeRecord);
                                return Result.success("支付成功");
                            } else {
                                log.info("分销类型为：0，所以查询用户分销人员表，但是无法查询到分销人员信息，不进行分销订单表插入");
                                return Result.success("支付成功，但是分销订单不插入");
                            }
                        } else if (course != null && course.getDistributionType() == 1) {
                            UserDistributorCourseRel userDistributorCourseRel = userDistributorCourseRelMapper
                                    .selectByStudentAndCourse(courseOrder.getUserId(), courseOrder.getCourseId());
                            if (userDistributorCourseRel != null) {
                                DistributeRecord distributeRecord = new DistributeRecord();
                                distributeRecord.setStudentId(courseOrder.getUserId());
                                distributeRecord.setDistributorId(userDistributorCourseRel.getDistributorId());
                                distributeRecord.setCourseId(courseOrder.getCourseId());
                                distributeRecord.setOrderId(courseOrder.getId());
                                distributeRecord.setActualPayAmount(request.getTotalAmount());
                                distributeRecord.setDistributionRatio(course.getDistributionRatio());
                                distributeRecord.setDistributeAmount(BigDecimal.valueOf(0));
                                distributeRecord.setStatus(Short.valueOf("0"));
                                distributeRecordMapper.insert(distributeRecord);
                                return Result.success("支付成功");
                            } else {
                                log.info("分销类型为：1，所以查询用户分销人员表，但是无法查询到分销人员信息，不进行分销订单表插入");
                                return Result.success("支付成功，但是分销订单不插入");
                            }
                        }
                    } else {
                        log.info("课程不存在,无法查询分销类型");
                        return Result.fail("支付成功，但是分销订单不插入");
                    }
                } else {
                    return Result.fail("订单不存在");
                }
            } else {
                ExamEnroll examEnroll = examEnrollMapper.selectByOrderNo(request.getOutTradeNo());
                if (examEnroll != null) {
                    ExamEnroll examEnroll1 = new ExamEnroll();
                    examEnroll1.setPayStatus(Short.valueOf("1"));
                    examEnroll1.setId(examEnroll.getId());
                    examEnroll1.setPayTime(LocalDateTime.now());
                    examEnroll1.setStatus(Short.valueOf("1"));
                    examEnrollMapper.updateById(examEnroll1);
                    return Result.success("支付成功");
                } else {
                    return Result.fail("订单不存在");
                }
            }
        }

        log.info("创建支付宝支付入参: {}", request);
        // 实体类注解参数校验
        Result<?> commonDataResponse = ValidationUtil.validInputParams(result);
        if (commonDataResponse != null) {
            return commonDataResponse;
        }
        try {
            return paymentStrategy.getPaymentService(request.getPayType()).createPayment(request);
        } catch (Exception e) {
            log.info("支付宝创建支付异常", e);
            return Result.fail("支付宝创建支付异常");
        }
    }

    /**
     * 支付宝同步回调
     */
    @GetMapping("/return/alipay/{scene}")
    public String alipayReturn(@PathVariable String scene, HttpServletRequest request, HttpServletResponse response) {
        // 处理支付宝同步回调
        // 1. 验证签名
        // 2. 获取订单信息
        // 3. 跳转到支付成功页面

        // Map<String, String[]> params = request.getParameterMap();
        // String outTradeNo = params.get("out_trade_no")[0]; // 暂时注释，未使用

        // 实际项目中应根据场景和订单号跳转到对应的页面
        // return "redirect:/payment/success?outTradeNo=" + outTradeNo + "&scene=" +
        // scene;
        String frontendUrl = "https://www.baidu.com";
        response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); // 301 永久重定向
        response.setHeader("Location", frontendUrl);
        return "redirect:" + frontendUrl;
    }

    /**
     * 支付宝异步通知（参考官方demo）
     */
    @PostMapping("/notify/alipay")
    public String alipayNotify(HttpServletRequest request) {
        try {
            // 获取通知参数 - 参考官方demo处理方式
            // 注意：支付宝回调参数都在 request.getParameterMap() 中
            Map<String, String> params = new java.util.HashMap<>();
            Map<String, String[]> requestParams = request.getParameterMap();

            for (Map.Entry<String, String[]> entry : requestParams.entrySet()) {
                String key = entry.getKey();
                String[] values = entry.getValue();
                String valueStr = "";
                for (int i = 0; i < values.length; i++) {
                    valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
                }
                // 将获取的值放入params中，注意编码问题
                params.put(key, valueStr);
            }

            // 检查关键参数
            if (!params.containsKey("sign")) {
                return "fail";
            }

            if (!params.containsKey("sign_type")) {
                params.put("sign_type", "RSA2");
            }

            // 处理通知 - 直接传递Map参数
            com.guomei.service.pay.AlipayService alipayService = (com.guomei.service.pay.AlipayService) paymentStrategy
                    .getPaymentService("alipay");
            boolean success = alipayService.handlePaymentNotify(params.toString());

            if (success) {
                return "success";
            } else {
                return "fail";
            }

        } catch (Exception e) {
            return "fail";
        }
    }

    /**
     * 支付宝异步通知（参考官方demo）
     */
    @GetMapping("/notify/alipay")
    public String redirectAlipayReturn(@RequestParam(required = false) String out_trade_no, 
                                     @RequestParam(required = false) String outTradeNo, 
                                     HttpServletRequest request,
                                     HttpServletResponse response) {
        // 处理不同的参数名称，优先使用 out_trade_no
        String tradeNo = out_trade_no != null ? out_trade_no : outTradeNo;
        
        // 如果参数为空，尝试从 queryString 中解析
        if (tradeNo == null || tradeNo.trim().isEmpty()) {
            String queryString = request.getQueryString();
            log.info("支付宝回调 queryString: {}", queryString);
            
            if (queryString != null && queryString.contains("out_trade_no=")) {
                // 解析 queryString 中的 out_trade_no 参数
                String[] params = queryString.split("&");
                for (String param : params) {
                    if (param.startsWith("out_trade_no=")) {
                        tradeNo = param.substring("out_trade_no=".length());
                        break;
                    }
                }
            }
        }
        
        if (tradeNo == null || tradeNo.trim().isEmpty()) {
            log.warn("支付宝回调缺少订单号参数，queryString: {}", request.getQueryString());
            return "订单号参数缺失";
        }
        
        log.info("支付宝回调处理订单: {}", tradeNo);
        if (tradeNo.startsWith("EXAM")) {
            // 重定向到考试界面
            ExamEnroll examEnroll = examEnrollMapper.selectByOrderNo(tradeNo);
            if (examEnroll != null) {
                examEnroll.setPayStatus(Short.valueOf("1"));
                examEnrollMapper.updateById(examEnroll);
                String frontendUrl = "https://ai.boundaryartai.com/exam-page/"+ examEnroll.getExamId();
                response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); // 301 永久重定向
                response.setHeader("Location", frontendUrl);
                return "redirect:" + frontendUrl;
            } else {
                return "订单不存在";
            }
        } else {
            CourseOrder courseOrder = courseOrderMapper.selectByOrderNo(tradeNo);
            if (courseOrder != null) {
                courseOrder.setPayStatus(Short.valueOf("1"));
                courseOrderMapper.updateById(courseOrder);
                // http://localhost:3000/course-detail/24
                String frontendUrl = "https://ai.boundaryartai.com/course-detail/"+ courseOrder.getCourseId();
                response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); // 301 永久重定向
                response.setHeader("Location", frontendUrl);
                return "redirect:" + frontendUrl;
            } else {
                return "订单不存在";
            }
        }
        
    }

    /**
     * 微信支付同步回调
     */
    @GetMapping("/return/wechat/{scene}")
    public String wechatReturn(@PathVariable String scene, HttpServletRequest request) {
        try {
            // 处理微信支付同步回调
            // 1. 验证签名
            // 2. 获取订单信息
            // 3. 跳转到支付成功页面

            Map<String, String[]> params = request.getParameterMap();
            String outTradeNo = params.get("out_trade_no") != null ? params.get("out_trade_no")[0] : null;

            log.info("微信支付同步回调: scene={}, outTradeNo={}", scene, outTradeNo);

            // 实际项目中应根据场景和订单号跳转到对应的页面
            // return "redirect:/payment/success?outTradeNo=" + outTradeNo + "&scene=" +
            // scene;
            return "微信支付成功页面";
        } catch (Exception e) {
            log.error("微信支付同步回调处理异常", e);
            return "支付失败页面";
        }
    }

    /**
     * 微信支付异步通知
     */
    @PostMapping("/notify/wechat")
    public String wechatNotify(HttpServletRequest request, @RequestBody String requestBody) {
        try {
            log.info("微信支付异步通知: {}", requestBody);

            // 获取请求头中的签名相关信息
            String signature = request.getHeader("Wechatpay-Signature");
            String timestamp = request.getHeader("Wechatpay-Timestamp");
            String nonce = request.getHeader("Wechatpay-Nonce");
            String serial = request.getHeader("Wechatpay-Serial");

            log.info("微信支付通知头信息: signature={}, timestamp={}, nonce={}, serial={}",
                    signature, timestamp, nonce, serial);

            // 处理微信支付通知
            boolean success = paymentStrategy.getPaymentService("wechat").handlePaymentNotify(requestBody);

            if (success) {
                // 微信支付要求返回特定格式
                return "{\"code\": \"SUCCESS\", \"message\": \"成功\"}";
            } else {
                return "{\"code\": \"FAIL\", \"message\": \"失败\"}";
            }
        } catch (Exception e) {
            log.error("微信支付异步通知处理异常", e);
            return "{\"code\": \"FAIL\", \"message\": \"处理异常\"}";
        }
    }

    /**
     * 查询支付状态（供前端轮询使用）
     */
    @GetMapping("/status")
    public Result<?> getPaymentStatus(@RequestParam(value = "orderNo", required = false) String orderNo) {
        try {
            log.info("前端轮询支付状态: orderNo={}", orderNo);

            if (orderNo == null || orderNo.trim().isEmpty()) {
                log.warn("支付状态查询缺少订单号参数");
                return Result.fail("订单号不能为空，请提供orderNo参数");
            }

            // 优先从Redis查询缓存的支付状态
            String redisKey = RedisConstants.PAYMENT_STATUS_PREFIX + orderNo;
            Object cachedStatus = redisUtils.get(redisKey);

            if (cachedStatus != null) {
                @SuppressWarnings("unchecked")
                Map<String, Object> cachedData = (Map<String, Object>) cachedStatus;
                log.info("从Redis获取支付状态: orderNo={}, status={}", orderNo, cachedData.get("status"));

                // 补充状态描述
                boolean success = (Boolean) cachedData.getOrDefault("success", false);
                cachedData.put("statusDesc", success ? "支付成功" : "待支付");

                return Result.success(cachedData);
            }

            // Redis中没有缓存，查询数据库
            CourseOrder order = courseOrderService.getByOrderNo(orderNo);
            if (order == null) {
                return Result.fail("订单不存在");
            }

            // 构建返回结果
            Map<String, Object> statusResult = new HashMap<>();
            statusResult.put("orderNo", order.getOrderNo());
            statusResult.put("payStatus", order.getPayStatus()); // 0-未支付,1-已支付,2-已取消
            statusResult.put("orderStatus", order.getOrderStatus()); // 0-成功 1-处理失败 2-待回调
            statusResult.put("payType", order.getPayType()); // 1-支付宝,2-微信
            statusResult.put("payTime", order.getPayTime());
            statusResult.put("amount", order.getPayAmount());

            // 根据支付状态返回不同的状态描述
            String statusDesc = getPaymentStatusDesc(order.getPayStatus(), order.getOrderStatus());
            statusResult.put("statusDesc", statusDesc);

            // 如果订单已支付，返回成功状态并缓存到Redis
            if (order.getPayStatus() != null && order.getPayStatus() == 1) {
                statusResult.put("success", true);
                statusResult.put("message", "支付成功");
                statusResult.put("status", "SUCCESS");

                // 缓存到Redis
                redisUtils.set(redisKey, statusResult, RedisConstants.PAYMENT_STATUS_EXPIRE);

                log.info("订单已支付: orderNo={}, payTime={}", orderNo, order.getPayTime());
                return Result.success(statusResult);
            }

            // 如果订单已取消，返回取消状态
            if (order.getPayStatus() != null && order.getPayStatus() == 2) {
                statusResult.put("success", false);
                statusResult.put("message", "订单已取消");
                statusResult.put("status", "CANCELLED");
                log.info("订单已取消: orderNo={}", orderNo);
                return Result.success(statusResult);
            }

            // 默认返回待支付状态
            statusResult.put("success", false);
            statusResult.put("message", "待支付");
            statusResult.put("status", "PENDING");

            log.info("订单待支付: orderNo={}, payStatus={}", orderNo, order.getPayStatus());
            return Result.success(statusResult);

        } catch (Exception e) {
            log.error("查询支付状态异常: orderNo={}", orderNo, e);
            return Result.fail("查询支付状态失败: " + e.getMessage());
        }
    }

    /**
     * 获取支付状态描述
     */
    private String getPaymentStatusDesc(Short payStatus, Short orderStatus) {
        if (payStatus == null) {
            return "待支付";
        }

        switch (payStatus) {
            case 0:
                return "待支付";
            case 1:
                if (orderStatus != null && orderStatus == 1) {
                    return "支付成功，处理异常";
                }
                return "支付成功";
            case 2:
                return "订单已取消";
            default:
                return "未知状态";
        }
    }

    /**
     * 测试接口 - 检查接口是否正常
     */
    @GetMapping("/test")
    public Result<?> testApi() {
        Map<String, Object> testResult = new HashMap<>();
        testResult.put("timestamp", System.currentTimeMillis());
        testResult.put("message", "支付接口正常");
        testResult.put("version", "1.0.0");
        return Result.success(testResult);
    }

    /**
     * 查询支付状态（原有接口保留）
     */
    @PostMapping("/query")
    public Result<?> queryPayment(@RequestBody Map<String, Object> params) {
        try {
            String payType = (String) params.get("payType");
            String outTradeNo = (String) params.get("outTradeNo");

            log.info("查询支付状态: payType={}, outTradeNo={}", payType, outTradeNo);

            if (payType == null || outTradeNo == null) {
                return Result.fail("支付类型和订单号不能为空");
            }

            return paymentStrategy.getPaymentService(payType).queryPayment(outTradeNo);
        } catch (Exception e) {
            log.error("查询支付状态异常", e);
            return Result.fail("查询支付状态失败: " + e.getMessage());
        }
    }
}
